package com.usooft.metaTalent.admin.system;

import com.usooft.framework.core.query.Page;
import com.usooft.framework.core.utils.MapBuilder;
import com.usooft.framework.web.auth.RequiresAuthentication;
import com.usooft.framework.web.auth.RequiresPermission;
import com.usooft.framework.web.auth.RequiresPermissionDependOn;
import com.usooft.framework.web.session.LoginSession;
import com.usooft.metaTalent.admin.system.form.EmployeeCreateForm;
import com.usooft.metaTalent.admin.system.form.EmployeeEditForm;
import com.usooft.metaTalent.admin.system.form.EmployeeListForm;
import com.usooft.metaTalent.core.system.entity.Employee;
import com.usooft.metaTalent.core.system.entity.EmployeeRole;
import com.usooft.metaTalent.core.system.entity.Role;
import com.usooft.metaTalent.core.system.query.EmployeeRoleQuery;
import com.usooft.metaTalent.core.system.query.RoleQuery;
import com.usooft.metaTalent.core.system.service.EmployeeRoleService;
import com.usooft.metaTalent.core.system.service.EmployeeService;
import com.usooft.metaTalent.core.system.service.RoleService;
import com.usooft.metaTalent.core.system.wrapper.EmployeeRoleWrapper;
import com.usooft.metaTalent.core.system.wrapper.EmployeeWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import static com.usooft.framework.core.utils.Checks.checkEquals;
import static com.usooft.framework.core.utils.FunctionUtils.*;

@RestController
@RequestMapping("/system/employee")
@RequiredArgsConstructor
public class EmployeeController {

    private final LoginSession loginSession;
    private final RoleService roleService;
    private final EmployeeService employeeService;
    private final EmployeeRoleService employeeRoleService;

    @GetMapping("/list")
    @RequiresPermission(value = "/system/employee/list", description = "员工/列表")
    public ResponseEntity<?> list(EmployeeListForm form) {
        Page<EmployeeWrapper> page = employeeService.page(form.buildQuery());
        Long[] employeeIds = mapToLongArray(page.getData(), Employee::getId);
        List<EmployeeRoleWrapper> employeeRoleWrappers = employeeIds.length > 0 ? employeeRoleService.list(EmployeeRoleQuery.builder()
                .wraps(EmployeeRoleQuery.Wraps.builder()
                        .role()
                        .build())
                .filter(EmployeeRoleQuery.Filter.builder()
                        .employeeIdIn(employeeIds)
                        .build())
                .build()) : Collections.emptyList();
        Map<Long, List<EmployeeRoleWrapper.Role>> employeeIdToRoles = group(employeeRoleWrappers, EmployeeRole::getEmployeeId, EmployeeRoleWrapper::getRole);
        return ResponseEntity.ok(MapBuilder.builder()
                .put("rows", page.getRows())
                .put("data", map(page.getData(), employee -> MapBuilder.builder()
                        .putObject(employee)
                        .put("roles", employeeIdToRoles.get(employee.getId()))
                        .build()))
                .build());
    }

    @PostMapping("/create")
    @RequiresPermission(value = "/system/employee/create", description = "员工/添加")
    public ResponseEntity<?> create(EmployeeCreateForm form) {
        employeeService.create(
                form.getName(),
                form.getPhoneNumber(),
                form.getGender(),
                form.getLocked()
        );
        return ResponseEntity.ok().build();
    }

    @PostMapping("/edit")
    @RequiresPermission(value = "/system/employee/edit", description = "员工/修改")
    public ResponseEntity<?> edit(EmployeeEditForm form) {
        Employee employee = employeeService.get(form.getId());
        employeeService.edit(
                employee,
                form.getName(),
                form.getPhoneNumber(),
                form.getGender(),
                form.getLocked()
        );
        return ResponseEntity.ok().build();
    }

    @GetMapping("/edit/get")
    @RequiresPermissionDependOn("/system/employee/edit")
    public ResponseEntity<?> createGet(Long id) {
        Employee employee = employeeService.get(id);
        return ResponseEntity.ok(MapBuilder.builder()
                .put("source", employee)
                .build());
    }

    @PostMapping("/lock")
    @RequiresPermission(value = "/system/employee/lock", description = "员工/禁用")
    public ResponseEntity<?> edit(Employee operator,
                                  Long id) {
        Employee employee = employeeService.get(id);
        employeeService.lock(employee);

        return ResponseEntity.ok().build();
    }

    @PostMapping("/unlock")
    @RequiresPermission(value = "/system/employee/unlock", description = "员工/启用")
    public ResponseEntity<?> unlock(Employee operator,
                                    Long id) {
        Employee employee = employeeService.get(id);
        employeeService.unlock(employee);

        return ResponseEntity.ok().build();
    }

    @PostMapping("/grant")
    @RequiresPermission(value = "/system/employee/grant", description = "员工/分配角色")
    public ResponseEntity<?> grant(Employee operator,
                                   Long id,
                                   Long[] roleIds) {
        Employee employee = employeeService.get(id);
        List<? extends Role> roles = (roleIds != null && roleIds.length > 0) ? roleService.list(RoleQuery.builder()
                .filter(RoleQuery.Filter.builder()
                        .idIn(roleIds)
                        .build())
                .build()) : Collections.emptyList();
        employeeRoleService.grant(employee, roles);

        return ResponseEntity.ok(MapBuilder.builder().build());
    }

    @GetMapping("/grant/get")
    @RequiresPermissionDependOn("/system/employee/grant")
    public ResponseEntity<?> grantGet(Long id) {
        Employee employee = employeeService.get(id);
        List<EmployeeRoleWrapper> employeeRoles = employeeRoleService.list(EmployeeRoleQuery.builder()
                .filter(EmployeeRoleQuery.Filter.builder()
                        .employeeIdIs(employee.getId())
                        .build())
                .build());

        List<? extends Role> roles = roleService.listAll();
        return ResponseEntity.ok(MapBuilder.builder()
                .put("source", MapBuilder.builder()
                        .put("roleIds", map(employeeRoles, EmployeeRole::getRoleId))
                        .build())
                .put("roles", roles)
                .build());
    }

    @PostMapping("/reset-password")
    @RequiresPermission(value = "/system/employee/reset-password", description = "员工/重置密码")
    public ResponseEntity<?> changePassword(Employee operator,
                                            Long id) {
        Employee employee = employeeService.get(id);
        String password = employeeService.resetPassword(employee);

        return ResponseEntity.ok(MapBuilder.builder()
                .put("password", password)
                .build());
    }

    @PostMapping("/change-password")
    @RequiresAuthentication
    public ResponseEntity<?> changePassword(Employee employee,
                                            String originalPassword,
                                            String newPassword,
                                            String confirmPassword) {
        checkEquals(newPassword, confirmPassword, "新密码两次输入不一致");
        employeeService.changePassword(employee, originalPassword, newPassword);
        loginSession.remove();

        return ResponseEntity.ok().build();
    }
}
